/**
 * SSE聊天服务
 */
import { v4 as uuidv4 } from 'uuid';
import { SSEEventType } from '../types/sse';
import instance from '../utils/request';
import { logDetailedError, debugLog } from '../utils/debugHelper';
import type { 
  SSEChatRequest,
  SSEEventData,
  SSEReplyEvent, 
  TokenStatEvent,
  ReferenceEvent,
  ThoughtEvent,
  ErrorEvent
} from '../types/sse';

// 应用密钥，实际项目中应从配置或环境变量获取
const BOT_APP_KEY = import.meta.env.VITE_BOT_BIZ_ID || 'tHIucAjz';
// SSE服务地址（使用代理地址）
const SSE_URL = import.meta.env.VITE_SSE_URL || '/api/sse';

/**
 * SSE连接状态
 */
export enum SSEConnectionStatus {
  CONNECTING = 'connecting',
  OPEN = 'open',
  CLOSED = 'closed',
  ERROR = 'error'
}

/**
 * SSE事件回调
 */
export interface SSECallbacks {
  onReply?: (event: SSEReplyEvent) => void;
  onTokenStat?: (event: TokenStatEvent) => void;
  onReference?: (event: ReferenceEvent) => void;
  onThought?: (event: ThoughtEvent) => void;
  onError?: (error: ErrorEvent['error']) => void;
  onConnectionStatusChange?: (status: SSEConnectionStatus) => void;
}

/**
 * SSE客户端类
 */
export class SSEClient {
  private controller: AbortController | null = null;
  private connectionStatus: SSEConnectionStatus = SSEConnectionStatus.CLOSED;
  private callbacks: SSECallbacks = {};
  private reader: ReadableStreamDefaultReader<Uint8Array> | null = null;
  private decoder: TextDecoder = new TextDecoder();
  private buffer: string = '';

  /**
   * 获取连接状态
   */
  public getConnectionStatus(): SSEConnectionStatus {
    return this.connectionStatus;
  }

  /**
   * 设置事件回调
   * @param callbacks 事件回调对象
   */
  public setCallbacks(callbacks: SSECallbacks): void {
    this.callbacks = { ...this.callbacks, ...callbacks };
  }

  /**
   * 发送聊天消息
   * @param content 消息内容
   * @param sessionId 会话ID
   * @param visitorId 访客ID
   * @param options 其他选项
   * @returns 请求ID
   */
  public sendChatMessage(
    content: string,
    sessionId: string,
    visitorId: string,
    options: Partial<Omit<SSEChatRequest, 'content' | 'session_id' | 'visitor_biz_id' | 'bot_app_key' | 'request_id'>> = {}
  ): string {
    // 关闭已有连接
    this.close();

    // 生成请求ID
    const requestId = uuidv4();

    // 构建请求参数
    const requestParams: SSEChatRequest = {
      request_id: requestId,
      content,
      session_id: sessionId,
      visitor_biz_id: visitorId,
      bot_app_key: BOT_APP_KEY,
      ...options
    };
console.log(BOT_APP_KEY)
    debugLog('发送聊天消息', { requestId, sessionId, content: content.substring(0, 50) + '...' });

    // 发送POST请求并处理SSE流
    this.connectWithFetch(requestParams);

    return requestId;
  }

  /**
   * 关闭SSE连接
   */
  public close(): void {
    // 避免多次关闭
    if (this.connectionStatus === SSEConnectionStatus.CLOSED) {
      return;
    }

    debugLog('关闭SSE连接');

    try {
      // 关闭reader
      if (this.reader) {
        try {
          this.reader.cancel().catch(error => {
            logDetailedError(error, '取消读取流时出错');
          });
        } catch (error) {
          logDetailedError(error, '取消读取流失败');
        } finally {
          this.reader = null;
        }
      }
      
      // 取消请求
      if (this.controller) {
        try {
          this.controller.abort();
        } catch (error) {
          logDetailedError(error, '中止控制器失败');
        } finally {
          this.controller = null;
        }
      }
    } catch (error) {
      logDetailedError(error, '关闭SSE连接时出错');
    } finally {
      // 清空缓冲区
      this.buffer = '';
      // 更新连接状态
      this.updateConnectionStatus(SSEConnectionStatus.CLOSED);
    }
  }

  /**
   * 使用fetch API建立SSE连接并发送POST请求
   * @param params 请求参数
   * @private
   */
  private async connectWithFetch(params: SSEChatRequest): Promise<void> {
    try {
      // 更新连接状态
      this.updateConnectionStatus(SSEConnectionStatus.CONNECTING);
      debugLog('连接SSE服务', { url: SSE_URL, method: 'POST', params: { ...params, content: params.content.substring(0, 20) + '...' } });

      // 创建AbortController用于取消请求
      this.controller = new AbortController();
      
      // 发送POST请求
      const response = await fetch(SSE_URL, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'text/event-stream',
          'Cache-Control': 'no-cache',
          'Connection': 'keep-alive',
        },
        body: JSON.stringify(params),
        credentials: 'include',
        signal: this.controller.signal
      });

      debugLog('收到服务器响应', { 
        status: response.status, 
        statusText: response.statusText,
        headers: Object.fromEntries([...response.headers.entries()])
      });

      if (!response.ok) {
        const errorText = await response.text().catch(() => '无法读取错误详情');
        throw new Error(`HTTP错误! 状态: ${response.status} ${response.statusText}, 详情: ${errorText}`);
      }

      // 检查内容类型是否为流
      const contentType = response.headers.get('Content-Type');
      if (contentType && !contentType.includes('text/event-stream')) {
        debugLog('警告: 响应内容类型不是 text/event-stream', { contentType });
      }

      if (!response.body) {
        throw new Error('响应没有body');
      }

      // 连接成功
      this.updateConnectionStatus(SSEConnectionStatus.OPEN);
      debugLog('SSE连接已建立', { url: SSE_URL });

      try {
        // 获取流并读取
        const reader = response.body.getReader();
        if (!reader) {
          throw new Error('无法获取响应流读取器');
        }
        
        this.reader = reader;
        
        // 读取流
        this.readStream();
      } catch (error) {
        throw new Error(`创建流读取器失败: ${error instanceof Error ? error.message : String(error)}`);
      }
    } catch (error) {
      // 如果是主动取消，不报错
      if (error instanceof Error && error.name === 'AbortError') {
        debugLog('SSE连接已取消');
        return;
      }
      
      logDetailedError(error, '建立SSE连接失败');
      this.handleError({ 
        code: 500, 
        message: `连接建立失败: ${error instanceof Error ? error.message : String(error)}` 
      });
    }
  }

  /**
   * 读取流数据
   * @private
   */
  private async readStream(): Promise<void> {
    if (!this.reader) {
      this.handleError({ 
        code: 500, 
        message: `读取流失败: reader对象为null` 
      });
      return;
    }

    try {
      while (true) {
        // 在每次读取前检查reader是否仍然有效
        if (!this.reader) {
          debugLog('SSE读取器已不存在，停止读取');
          break;
        }

        const { value, done } = await this.reader.read();
        
        if (done) {
          debugLog('SSE流已结束');
          this.close();
          break;
        }
        
        // 解码并处理数据
        const chunk = this.decoder.decode(value, { stream: true });
        this.buffer += chunk;
        
        // 处理缓冲区中的事件
        this.processBuffer();
      }
    } catch (error) {
      // 如果是主动取消，不报错
      if (error instanceof Error && error.name === 'AbortError') {
        debugLog('SSE读取已取消');
        return;
      }
      
      logDetailedError(error, '读取SSE流失败');
      this.handleError({ 
        code: 500, 
        message: `读取流失败: ${error instanceof Error ? error.message : String(error)}` 
      });
    } finally {
      // 确保连接和资源被正确关闭
      this.close();
    }
  }

  /**
   * 处理缓冲区中的SSE事件
   * @private
   */
  private processBuffer(): void {
    // 按行分割
    const lines = this.buffer.split('\n');
    
    // 最后一行可能不完整，保留在缓冲区
    this.buffer = lines.pop() || '';
    
    let eventType = '';
    let data = '';
    
    // 处理每一行
    for (const line of lines) {
      if (line.trim() === '') {
        // 空行表示事件结束，处理事件
        if (eventType && data) {
          this.handleEventData(eventType, data);
          eventType = '';
          data = '';
        }
      } else if (line.startsWith('event:')) {
        eventType = line.substring(6).trim();
      } else if (line.startsWith('data:')) {
        data = line.substring(5).trim();
      }
    }
  }

  /**
   * 处理SSE事件数据
   * @param eventType 事件类型
   * @param data 事件数据
   * @private
   */
  private handleEventData(eventType: string, data: string): void {
    try {
      debugLog('处理SSE事件', { type: eventType, data: data.substring(0, 100) + (data.length > 100 ? '...' : '') });
      
      // 解析事件数据
      const eventData = JSON.parse(data) as SSEEventData;
      
      // 根据事件类型分发到对应的回调
      switch (eventType as SSEEventType) {
        case SSEEventType.REPLY:
          if (this.callbacks.onReply && 'payload' in eventData) {
            if((eventData.payload as SSEReplyEvent).reply_method != 0) {
                this.callbacks.onReply(eventData.payload as SSEReplyEvent);
                // 如果是最终回复且不是错误，则关闭连接
                if ((eventData.payload as SSEReplyEvent).is_final && !(eventData.payload as SSEReplyEvent).is_evil) {
                  debugLog('收到最终回复，关闭连接');
                //   this.close();
                }
            }
          }
          break;
        case SSEEventType.TOKEN_STAT:
          if (this.callbacks.onTokenStat && 'payload' in eventData) {
            this.callbacks.onTokenStat(eventData.payload as TokenStatEvent);
          }
          break;
        case SSEEventType.REFERENCE:
          if (this.callbacks.onReference && 'payload' in eventData) {
            this.callbacks.onReference(eventData.payload as ReferenceEvent);
          }
          break;
        case SSEEventType.THOUGHT:
          if (this.callbacks.onThought && 'payload' in eventData) {
            const thoughtEvent = eventData.payload as ThoughtEvent;
            this.callbacks.onThought(thoughtEvent);
            
            // 检查是否为最终思考事件(status为success)
            const isCompleteThought = thoughtEvent.procedures && 
                                     thoughtEvent.procedures.length > 0 &&
                                     thoughtEvent.procedures[0].status === 'success';
            
            // if (isCompleteThought) {
            //   debugLog('收到最终思考事件(status: success)，关闭连接');
            //   this.close();
            // } else {
            //   debugLog('收到中间思考事件(status: processing)，继续保持连接');
            // }
          }
          break;
        case SSEEventType.ERROR:
          if (this.callbacks.onError && 'error' in eventData) {
            debugLog('收到错误事件', eventData.error);
            this.callbacks.onError(eventData.error);
            this.close();
          }
          break;
        default:
          console.warn(`未知事件类型: ${eventType}`);
      }
    } catch (error) {
      logDetailedError(error, '处理SSE事件失败');
      this.handleError({ 
        code: 500, 
        message: `事件处理失败: ${error instanceof Error ? error.message : String(error)}` 
      });
    }
  }

  /**
   * 更新连接状态
   * @param status 新状态
   * @private
   */
  private updateConnectionStatus(status: SSEConnectionStatus): void {
    if (this.connectionStatus !== status) {
      debugLog('SSE连接状态变更', { from: this.connectionStatus, to: status });
      this.connectionStatus = status;
      if (this.callbacks.onConnectionStatusChange) {
        this.callbacks.onConnectionStatusChange(status);
      }
    }
  }

  /**
   * 处理错误
   * @param error 错误信息
   * @private
   */
  private handleError(error: ErrorEvent['error']): void {
    logDetailedError(error, 'SSE错误');
    this.updateConnectionStatus(SSEConnectionStatus.ERROR);
    if (this.callbacks.onError) {
      this.callbacks.onError(error);
    }
    this.close();
  }
}

// 创建并导出全局SSE客户端实例
export const sseClient = new SSEClient(); 